package com.aiyige.model;

import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import com.aiyige.arouter.Router;
import com.aiyige.model.tag.Tag;
import com.aiyige.setup.util.SetupUtil;

import java.io.Serializable;
import java.net.URLEncoder;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by zhuyakun on 2018/1/18.
 */

public class User implements Parcelable{
    public static final String GENDER_MALE = "m";
    public static final String GENDER_FEMALE = "f";
    public static final String GENDER_UNKNOWN = "x";
    public static final String TOKEN_TYPE_GUEST = "basic";
    public static final String TOKEN_TYPE_USER = "bearer";
    String id;
    String account;
    String password;
    String salt;
    String avatar;
    String miniAvatar;
    String mobile;
    String router;
    Integer mobileVerified;
    Integer level;
    Integer status;
    Long createTime;
    Long updateTime;
    String token;
    ThirdOauthBackup thirdOauthBackup;
    List<SlideImage> slideBackup;
    MoreBackup moreBackup;
    StatisticsBackup statisticsBackup;
    MineBackup mineBackup;
    Long loginTimestamp;
    TokenBackup accessToken;
    List<Tag> columnBackup;
    Tag channel;
    List<Tag> avocation;
    boolean newUser;
    IMBackup userAccidPassword;


    WalletPassword walletPassword;

    public String getRouter() {
        if (!TextUtils.isEmpty(router)) {
            return router;
        } else {
            return Router.generateUserPageRouter(id);
        }
    }

    public void setRouter(String router) {
        this.router = router;
    }

    public boolean isHasWalletPassword() {
        return hasWalletPassword;
    }

    public void setHasWalletPassword(boolean hasWalletPassword) {
        this.hasWalletPassword = hasWalletPassword;
    }

    boolean hasWalletPassword;


    public User() {
        router = "";
        id = "";
        account = "";
        password = "";
        salt = "";
        avatar = "";
        miniAvatar = "";
        mobile = "";
        mobileVerified = 0;
        level = 0;
        status = 0;
        token = "";
        newUser = false;
        thirdOauthBackup = new ThirdOauthBackup();
        slideBackup = new LinkedList<>();
        moreBackup = new MoreBackup();
        statisticsBackup = new StatisticsBackup();
        mineBackup = new MineBackup();
        columnBackup = new LinkedList<>();
        channel = Tag.newBuilder().groupType(SetupUtil.GROUP_TYPE_CHANNEL).build();
        avocation = new LinkedList<>();
        loginTimestamp = 0L;
        accessToken = new TokenBackup();
        walletPassword = new WalletPassword();
        userAccidPassword = new IMBackup();
    }

    public User(User other) {
        this.router = other.router == null ? "" : other.router;
        this.id = other.id == null ? "" : other.id;
        this.account = other.account == null ? "" : other.account;
        this.password = other.password == null ? "" : other.password;
        this.salt = other.salt == null ? "" : other.salt;
        this.avatar = other.avatar == null ? "" : other.avatar;
        this.miniAvatar = other.miniAvatar == null ? "" : other.miniAvatar;
        this.mobile = other.mobile == null ? "" : other.mobile;
        this.mobileVerified = other.mobileVerified;
        this.level = other.level;
        this.status = other.status;
        this.createTime = other.createTime;
        this.updateTime = other.updateTime;
        this.token = other.token == null ? "" : other.token;
        this.thirdOauthBackup = other.thirdOauthBackup == null ? new ThirdOauthBackup() : other.thirdOauthBackup;
        this.slideBackup = other.slideBackup == null ? new LinkedList<SlideImage>() : other.slideBackup;
        this.moreBackup = other.moreBackup == null ? new MoreBackup() : other.moreBackup;
        this.statisticsBackup = other.statisticsBackup == null ? new StatisticsBackup() : other.statisticsBackup;
        this.mineBackup = other.mineBackup == null ? new MineBackup() : other.mineBackup;
        this.loginTimestamp = other.loginTimestamp;
        this.accessToken = other.accessToken == null ? new TokenBackup() : other.accessToken;
        this.columnBackup = other.columnBackup == null ? new LinkedList<Tag>() : other.columnBackup;
        this.channel = other.channel == null ? Tag.newBuilder().groupType(SetupUtil.GROUP_TYPE_CHANNEL).build() : other.channel;
        this.avocation = other.avocation == null ? new LinkedList<Tag>() : other.avocation;
        this.newUser = other.newUser;
        this.walletPassword = other.walletPassword == null ? new WalletPassword() : other.walletPassword;
        this.userAccidPassword = other.userAccidPassword == null ? new IMBackup() : other.userAccidPassword;
    }

    private User(Builder builder) {
        setRouter(builder.router);
        setId(builder.id);
        setAccount(builder.account);
        setPassword(builder.password);
        setSalt(builder.salt);
        setAvatar(builder.avatar);
        setMiniAvatar(builder.miniAvatar);
        setMobile(builder.mobile);
        setMobileVerified(builder.mobileVerified);
        setLevel(builder.level);
        setStatus(builder.status);
        setCreateTime(builder.createTime);
        setUpdateTime(builder.updateTime);
        setToken(builder.token);
        setThirdOauthBackup(builder.thirdOauthBackup);
        setSlideBackup(builder.slideBackup);
        setMoreBackup(builder.moreBackup);
        setStatisticsBackup(builder.statisticsBackup);
        setMineBackup(builder.mineBackup);
        setLoginTimestamp(builder.loginTimestamp);
        setAccessToken(builder.accessToken);
        setChannel(builder.channel);
        setAvocation(builder.avocation);
        setColumnBackup(builder.columnBackup);
        setNewUser(builder.newUser);
        setWalletPassword(builder.walletPassword);
        setHasWalletPassword(builder.hasWalletPassword);
        setUserAccidPassword(builder.userAccidPassword);
    }

    public IMBackup getUserAccidPassword() {
        return userAccidPassword;
    }

    public void setUserAccidPassword(IMBackup userAccidPassword) {
        this.userAccidPassword = userAccidPassword;
    }

    public boolean isNewUser() {
        return newUser;
    }

    public void setNewUser(boolean newUser) {
        this.newUser = newUser;
    }

    public Long getLoginTimestamp() {
        return loginTimestamp;
    }

    public void setLoginTimestamp(Long loginTimestamp) {
        this.loginTimestamp = loginTimestamp;
    }

    public static Builder newBuilder() {
        return new Builder();
    }


    public TokenBackup getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(TokenBackup accessToken) {
        this.accessToken = accessToken;
    }

    public Tag getChannel() {
        return channel;
    }

    public void setChannel(Tag channel) {
        this.channel = channel;
    }

    public List<Tag> getAvocation() {
        return avocation;
    }

    public void setAvocation(List<Tag> avocation) {
        this.avocation = avocation;
    }

    public List<Tag> getColumnBackup() {
        return columnBackup;
    }

    public void setColumnBackup(List<Tag> column) {
        this.columnBackup = column;
    }


    public String getId() {
        return id;
    }

    public String getIdUrlEncoded() {
        if (TextUtils.isEmpty(id)) return "";
        try {
            return URLEncoder.encode(id, "utf-8");
        } catch (Exception e) {
            return id;
        }
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAccount() {
        return TextUtils.isEmpty(account) ? "" : account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getAvatar() {
        return TextUtils.isEmpty(avatar) ? "" : avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getMiniAvatar() {
        return miniAvatar;
    }

    public void setMiniAvatar(String miniAvatar) {
        this.miniAvatar = miniAvatar;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public Integer getMobileVerified() {
        return mobileVerified;
    }

    public void setMobileVerified(Integer mobileVerified) {
        this.mobileVerified = mobileVerified;
    }

    public Integer getLevel() {
        return level;
    }

    public void setLevel(Integer level) {
        this.level = level;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Long createTime) {
        this.createTime = createTime;
    }

    public Long getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Long updateTime) {
        this.updateTime = updateTime;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public ThirdOauthBackup getThirdOauthBackup() {
        return thirdOauthBackup;
    }

    public void setThirdOauthBackup(ThirdOauthBackup thirdOauthBackup) {
        this.thirdOauthBackup = thirdOauthBackup;
    }

    public List<SlideImage> getSlideBackup() {
        return slideBackup;
    }

    public void setSlideBackup(List<SlideImage> slideBackup) {
        this.slideBackup = slideBackup;
    }

    public MoreBackup getMoreBackup() {
        return moreBackup;
    }

    public void setMoreBackup(MoreBackup moreBackup) {
        this.moreBackup = moreBackup;
    }

    public StatisticsBackup getStatisticsBackup() {
        return statisticsBackup;
    }

    public void setStatisticsBackup(StatisticsBackup statisticsBackup) {
        this.statisticsBackup = statisticsBackup;
    }

    public MineBackup getMineBackup() {
        return mineBackup;
    }

    public void setMineBackup(MineBackup mineBackup) {
        this.mineBackup = mineBackup;
    }


    public WalletPassword getWalletPassword() {
        return walletPassword;
    }

    public void setWalletPassword(WalletPassword walletPassword) {
        this.walletPassword = walletPassword;
    }

    public static class WalletPassword implements Serializable{
        String password;
        String mobile;
        String code;

        public WalletPassword(String password, String mobile, String code) {
            this.password = password;
            this.mobile = mobile;
            this.code = code;
        }

        public WalletPassword() {
        }

        public String getPassword() {
            return password == null ? "" : password;
        }

        public void setPassword(String password) {
            this.password = password == null ? "" : password;
        }

        public String getMobile() {
            return mobile == null ? "" : mobile;
        }

        public void setMobile(String mobile) {
            this.mobile = mobile == null ? "" : mobile;
        }

        public String getCode() {
            return code == null ? "" : code;
        }

        public void setCode(String code) {
            this.code = code == null ? "" : code;
        }
    }

    public static class ThirdOauthBackup implements Parcelable{
        protected static final long serialVersionUID = 10001L;
        String id;
        String source;
        String uid;
        String openid;
        String unionid;
        String avatar;
        String nickName;
        String accessToken;
        Long accessTokenExpire;
        String refreshToken;
        Long refreshTokenExpire;

        public ThirdOauthBackup() {
            id = "";
            source = "";
            uid = "";
            openid = "";
            unionid = "";
            avatar = "";
            nickName = "";
            accessToken = "";
            accessTokenExpire = 0l;
            refreshToken = "";
            refreshTokenExpire = 0l;
        }

        private ThirdOauthBackup(Builder builder) {
            setId(builder.id);
            setSource(builder.source);
            setUid(builder.uid);
            setOpenid(builder.openid);
            setUnionid(builder.unionid);
            setAvatar(builder.avatar);
            setAccessToken(builder.accessToken);
            setAccessTokenExpire(builder.accessTokenExpire);
            setRefreshToken(builder.refreshToken);
            setRefreshTokenExpire(builder.refreshTokenExpire);
            setNickName(builder.nickName);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getSource() {
            return source;
        }

        public void setSource(String source) {
            this.source = source;
        }

        public String getUid() {
            return uid;
        }

        public void setUid(String uid) {
            this.uid = uid;
        }

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }

        public String getAvatar() {
            return avatar;
        }

        public void setAvatar(String avatar) {
            this.avatar = avatar;
        }

        public String getAccessToken() {
            return accessToken;
        }

        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }

        public Long getAccessTokenExpire() {
            return accessTokenExpire;
        }

        public void setAccessTokenExpire(Long accessTokenExpire) {
            this.accessTokenExpire = accessTokenExpire;
        }

        public String getRefreshToken() {
            return refreshToken;
        }

        public void setRefreshToken(String refreshToken) {
            this.refreshToken = refreshToken;
        }

        public Long getRefreshTokenExpire() {
            return refreshTokenExpire;
        }

        public void setRefreshTokenExpire(Long refreshTokenExpire) {
            this.refreshTokenExpire = refreshTokenExpire;
        }

        public String getNickName() {
            return nickName;
        }

        public void setNickName(String nickName) {
            this.nickName = nickName;
        }


        public static final class Builder {
            private String id;
            private String source;
            private String uid;
            private String openid;
            private String nickName;
            private String unionid;
            private String avatar;
            private String accessToken;
            private Long accessTokenExpire;
            private String refreshToken;
            private Long refreshTokenExpire;

            private Builder() {
                id = null;
                source = null;
                uid = null;
                openid = null;
                unionid = null;
                nickName = null;
                avatar = null;
                accessToken = null;
                accessTokenExpire = null;
                refreshToken = null;
                refreshTokenExpire = null;

            }

            public Builder id(String id) {
                this.id = id;
                return this;
            }

            public Builder source(String source) {
                this.source = source;
                return this;
            }

            public Builder uid(String uid) {
                this.uid = uid;
                return this;
            }

            public Builder openid(String openid) {
                this.openid = openid;
                return this;
            }

            public Builder unionid(String unionid) {
                this.unionid = unionid;
                return this;
            }

            public Builder avatar(String avatar) {
                this.avatar = avatar;
                return this;
            }

            public Builder accessToken(String accessToken) {
                this.accessToken = accessToken;
                return this;
            }

            public Builder accessTokenExpire(Long accessTokenExpire) {
                this.accessTokenExpire = accessTokenExpire;
                return this;
            }

            public Builder refreshToken(String refreshToken) {
                this.refreshToken = refreshToken;
                return this;
            }

            public Builder refreshTokenExpire(Long refreshTokenExpire) {
                this.refreshTokenExpire = refreshTokenExpire;
                return this;
            }

            public Builder nickName(String nickName) {
                this.nickName = nickName;
                return this;
            }


            public ThirdOauthBackup build() {
                return new ThirdOauthBackup(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.id);
            dest.writeString(this.source);
            dest.writeString(this.uid);
            dest.writeString(this.openid);
            dest.writeString(this.unionid);
            dest.writeString(this.avatar);
            dest.writeString(this.nickName);
            dest.writeString(this.accessToken);
            dest.writeValue(this.accessTokenExpire);
            dest.writeString(this.refreshToken);
            dest.writeValue(this.refreshTokenExpire);
        }

        protected ThirdOauthBackup(Parcel in) {
            this.id = in.readString();
            this.source = in.readString();
            this.uid = in.readString();
            this.openid = in.readString();
            this.unionid = in.readString();
            this.avatar = in.readString();
            this.nickName = in.readString();
            this.accessToken = in.readString();
            this.accessTokenExpire = (Long) in.readValue(Long.class.getClassLoader());
            this.refreshToken = in.readString();
            this.refreshTokenExpire = (Long) in.readValue(Long.class.getClassLoader());
        }

        public static final Creator<ThirdOauthBackup> CREATOR = new Creator<ThirdOauthBackup>() {
            @Override
            public ThirdOauthBackup createFromParcel(Parcel source) {
                return new ThirdOauthBackup(source);
            }

            @Override
            public ThirdOauthBackup[] newArray(int size) {
                return new ThirdOauthBackup[size];
            }
        };
    }

    public static class SlideImage implements Parcelable{
        String id;
        String userId;
        String url;
        String title;
        String router;

        public SlideImage() {
            id = "";
            userId = "";
            url = "";
            title = "";
            router = "";
        }

        private SlideImage(Builder builder) {
            setId(builder.id);
            setUserId(builder.userId);
            setUrl(builder.url);
            setTitle(builder.title);
            setRouter(builder.router);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getRouter() {
            return router;
        }

        public void setRouter(String router) {
            this.router = router;
        }


        public static final class Builder {
            private String id;
            private String userId;
            private String url;
            private String title;
            private String router;

            private Builder() {
                id = null;
                userId = null;
                url = null;
                title = null;
                router = null;
            }

            public Builder id(String id) {
                this.id = id;
                return this;
            }

            public Builder userId(String userId) {
                this.userId = userId;
                return this;
            }

            public Builder url(String url) {
                this.url = url;
                return this;
            }

            public Builder title(String title) {
                this.title = title;
                return this;
            }

            public Builder router(String router) {
                this.router = router;
                return this;
            }

            public SlideImage build() {
                return new SlideImage(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.id);
            dest.writeString(this.userId);
            dest.writeString(this.url);
            dest.writeString(this.title);
            dest.writeString(this.router);
        }

        protected SlideImage(Parcel in) {
            this.id = in.readString();
            this.userId = in.readString();
            this.url = in.readString();
            this.title = in.readString();
            this.router = in.readString();
        }

        public static final Creator<SlideImage> CREATOR = new Creator<SlideImage>() {
            @Override
            public SlideImage createFromParcel(Parcel source) {
                return new SlideImage(source);
            }

            @Override
            public SlideImage[] newArray(int size) {
                return new SlideImage[size];
            }
        };
    }

    public static class MoreBackup implements Parcelable{
        String id;
        String sex;
        Long birthDate;
        String email;
        String telphone;
        String zipCode;
        String identityCard;
        String city;
        String country;
        String introduce;
        String webUrl;
        boolean bindWeixin;
        boolean bindQQ;
        boolean bindSina;

        public MoreBackup() {
            id = "";
            sex = "";
            email = "";
            telphone = "";
            zipCode = "";
            identityCard = "";
            city = "";
            country = "";
            introduce = "";
            birthDate = null;
            webUrl = "";
            bindWeixin = false;
            bindQQ = false;
            bindSina = false;
        }

        private MoreBackup(Builder builder) {
            setId(builder.id);
            setSex(builder.sex);
            setBirthDate(builder.birthDate);
            setEmail(builder.email);
            setTelphone(builder.telphone);
            setZipCode(builder.zipCode);
            setIdentityCard(builder.identityCard);
            setCity(builder.city);
            setCountry(builder.country);
            setIntroduce(builder.introduce);
            setWebUrl(builder.webUrl);
            setBindQQ(builder.bindQQ);
            setBindWeixin(builder.bindWeixin);
            setBindSina(builder.bindSina);
        }


        public static Builder newBuilder() {
            return new Builder();
        }

        public String getWebUrl() {
            return webUrl;
        }

        public void setWebUrl(String webUrl) {
            this.webUrl = webUrl;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public Long getBirthDate() {
            return birthDate;
        }

        public void setBirthDate(Long birthDate) {
            this.birthDate = birthDate;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public String getTelphone() {
            return telphone;
        }

        public void setTelphone(String telphone) {
            this.telphone = telphone;
        }

        public String getZipCode() {
            return zipCode;
        }

        public void setZipCode(String zipCode) {
            this.zipCode = zipCode;
        }

        public String getIdentityCard() {
            return identityCard;
        }

        public void setIdentityCard(String identityCard) {
            this.identityCard = identityCard;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getIntroduce() {
            return introduce;
        }

        public void setIntroduce(String introduce) {
            this.introduce = introduce;
        }

        public boolean isBindWeixin() {
            return bindWeixin;
        }

        public void setBindWeixin(boolean bindWeixin) {
            this.bindWeixin = bindWeixin;
        }

        public boolean isBindQQ() {
            return bindQQ;
        }

        public void setBindQQ(boolean bindQQ) {
            this.bindQQ = bindQQ;
        }

        public boolean isBindSina() {
            return bindSina;
        }

        public void setBindSina(boolean bindSina) {
            this.bindSina = bindSina;
        }

        public static final class Builder {
            private String id;
            private String sex;
            private Long birthDate;
            private String email;
            private String telphone;
            private String zipCode;
            private String identityCard;
            private String city;
            private String country;
            private String introduce;
            private String webUrl;
            private boolean bindWeixin;
            private boolean bindQQ;
            private boolean bindSina;

            private Builder() {
                id = null;
                sex = null;
                birthDate = null;
                email = null;
                telphone = null;
                zipCode = null;
                identityCard = null;
                city = null;
                country = null;
                introduce = null;
                webUrl = null;
                bindWeixin = false;
                bindQQ = false;
                bindSina = false;
            }


            public Builder id(String id) {
                this.id = id;
                return this;
            }

            public Builder webUrl(String webUrl) {
                this.webUrl = webUrl;
                return this;
            }

            public Builder sex(String sex) {
                this.sex = sex;
                return this;
            }

            public Builder birthDate(Long birthDate) {
                this.birthDate = birthDate;
                return this;
            }

            public Builder email(String email) {
                this.email = email;
                return this;
            }

            public Builder telphone(String telphone) {
                this.telphone = telphone;
                return this;
            }

            public Builder zipCode(String zipCode) {
                this.zipCode = zipCode;
                return this;
            }

            public Builder identityCard(String identityCard) {
                this.identityCard = identityCard;
                return this;
            }

            public Builder city(String city) {
                this.city = city;
                return this;
            }

            public Builder country(String country) {
                this.country = country;
                return this;
            }

            public Builder introduce(String introduce) {
                this.introduce = introduce;
                return this;
            }

            public Builder bindWeixin(boolean bindWeixin) {
                this.bindWeixin = bindWeixin;
                return this;
            }

            public Builder bindQQ(boolean bindQQ) {
                this.bindQQ = bindQQ;
                return this;
            }

            public Builder bindSina(boolean bindSina) {
                this.bindSina = bindSina;
                return this;
            }

            public MoreBackup build() {
                return new MoreBackup(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.id);
            dest.writeString(this.sex);
            dest.writeValue(this.birthDate);
            dest.writeString(this.email);
            dest.writeString(this.telphone);
            dest.writeString(this.zipCode);
            dest.writeString(this.identityCard);
            dest.writeString(this.city);
            dest.writeString(this.country);
            dest.writeString(this.introduce);
            dest.writeString(this.webUrl);
            dest.writeByte(this.bindWeixin ? (byte) 1 : (byte) 0);
            dest.writeByte(this.bindQQ ? (byte) 1 : (byte) 0);
            dest.writeByte(this.bindSina ? (byte) 1 : (byte) 0);
        }

        protected MoreBackup(Parcel in) {
            this.id = in.readString();
            this.sex = in.readString();
            this.birthDate = (Long) in.readValue(Long.class.getClassLoader());
            this.email = in.readString();
            this.telphone = in.readString();
            this.zipCode = in.readString();
            this.identityCard = in.readString();
            this.city = in.readString();
            this.country = in.readString();
            this.introduce = in.readString();
            this.webUrl = in.readString();
            this.bindWeixin = in.readByte() != 0;
            this.bindQQ = in.readByte() != 0;
            this.bindSina = in.readByte() != 0;
        }

        public static final Creator<MoreBackup> CREATOR = new Creator<MoreBackup>() {
            @Override
            public MoreBackup createFromParcel(Parcel source) {
                return new MoreBackup(source);
            }

            @Override
            public MoreBackup[] newArray(int size) {
                return new MoreBackup[size];
            }
        };
    }

    public static class StatisticsBackup implements Parcelable{
        long followersCount;
        long followCount;
        long viewCount;
        long sellCount;
        double transactionAmount;
        long dynamicCount;
        long favoriteCount;
        double purseBalance;
        long waitPayCount;
        long orderCount;
        long interestCount;
        long browseCount;
        long productSellCount;
        double productSellAmount;
        long productCount;
        long onlineDynamicCount;
        long couponCount;

        public long getOnlineDynamicCount() {
            return onlineDynamicCount;
        }

        public void setOnlineDynamicCount(long onlineDynamicCount) {
            this.onlineDynamicCount = onlineDynamicCount;
        }

        public long getProductCount() {
            return productCount;
        }

        public void setProductCount(long productCount) {
            this.productCount = productCount;
        }

        public long getProductSellCount() {
            return productSellCount;
        }

        public void setProductSellCount(long productSellCount) {
            this.productSellCount = productSellCount;
        }

        public double getProductSellAmount() {
            return productSellAmount;
        }

        public void setProductSellAmount(double productSellAmount) {
            this.productSellAmount = productSellAmount;
        }

        public long getBrowseCount() {
            return browseCount;
        }

        public void setBrowseCount(long browseCount) {
            this.browseCount = browseCount;
        }

        public long getDynamicCount() {
            return dynamicCount;
        }

        public void setDynamicCount(long dynamicCount) {
            this.dynamicCount = dynamicCount;
        }

        public long getFavoriteCount() {
            return favoriteCount;
        }

        public void setFavoriteCount(long favoriteCount) {
            this.favoriteCount = favoriteCount;
        }

        public double getPurseBalance() {
            return purseBalance;
        }

        public void setPurseBalance(double purseBalance) {
            this.purseBalance = purseBalance;
        }

        public long getWaitPayCount() {
            return waitPayCount;
        }

        public void setWaitPayCount(long waitPayCount) {
            this.waitPayCount = waitPayCount;
        }

        public long getOrderCount() {
            return orderCount;
        }

        public void setOrderCount(long orderCount) {
            this.orderCount = orderCount;
        }

        public long getInterestCount() {
            return interestCount;
        }

        public void setInterestCount(long interestCount) {
            this.interestCount = interestCount;
        }

        public long getFollowersCount() {
            return followersCount;
        }

        public void setFollowersCount(long followersCount) {
            this.followersCount = followersCount;
        }

        public long getFollowCount() {
            return followCount;
        }

        public void setFollowCount(long followCount) {
            this.followCount = followCount;
        }

        public long getViewCount() {
            return viewCount;
        }

        public void setViewCount(long viewCount) {
            this.viewCount = viewCount;
        }

        public long getSellCount() {
            return sellCount;
        }

        public void setSellCount(long sellCount) {
            this.sellCount = sellCount;
        }

        public double getTransactionAmount() {
            return transactionAmount;
        }

        public void setTransactionAmount(double transactionAmount) {
            this.transactionAmount = transactionAmount;
        }

        public long getCouponCount() {
            return couponCount;
        }

        public void setCouponCount(long couponCount) {
            this.couponCount = couponCount;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeLong(this.followersCount);
            dest.writeLong(this.followCount);
            dest.writeLong(this.viewCount);
            dest.writeLong(this.sellCount);
            dest.writeDouble(this.transactionAmount);
            dest.writeLong(this.dynamicCount);
            dest.writeLong(this.favoriteCount);
            dest.writeDouble(this.purseBalance);
            dest.writeLong(this.waitPayCount);
            dest.writeLong(this.orderCount);
            dest.writeLong(this.interestCount);
            dest.writeLong(this.browseCount);
            dest.writeLong(this.productSellCount);
            dest.writeDouble(this.productSellAmount);
            dest.writeLong(this.productCount);
            dest.writeLong(this.onlineDynamicCount);
            dest.writeLong(this.couponCount);
        }

        public StatisticsBackup() {
        }

        protected StatisticsBackup(Parcel in) {
            this.followersCount = in.readLong();
            this.followCount = in.readLong();
            this.viewCount = in.readLong();
            this.sellCount = in.readLong();
            this.transactionAmount = in.readDouble();
            this.dynamicCount = in.readLong();
            this.favoriteCount = in.readLong();
            this.purseBalance = in.readDouble();
            this.waitPayCount = in.readLong();
            this.orderCount = in.readLong();
            this.interestCount = in.readLong();
            this.browseCount = in.readLong();
            this.productSellCount = in.readLong();
            this.productSellAmount = in.readDouble();
            this.productCount = in.readLong();
            this.onlineDynamicCount = in.readLong();
            this.couponCount = in.readLong();
        }

        public static final Creator<StatisticsBackup> CREATOR = new Creator<StatisticsBackup>() {
            @Override
            public StatisticsBackup createFromParcel(Parcel source) {
                return new StatisticsBackup(source);
            }

            @Override
            public StatisticsBackup[] newArray(int size) {
                return new StatisticsBackup[size];
            }
        };
    }

    public static class MineBackup implements Parcelable{
        String userFollowId;
        boolean mutualFollower;

        public MineBackup() {
            userFollowId = "";
            mutualFollower = false;
        }

        private MineBackup(Builder builder) {
            setUserFollowId(builder.userFollowId);
            setMutualFollower(builder.mutualFollower);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public String getUserFollowId() {
            return userFollowId;
        }

        public void setUserFollowId(String userFollowId) {
            this.userFollowId = userFollowId;
        }

        public boolean isMutualFollower() {
            return mutualFollower;
        }

        public void setMutualFollower(boolean mutualFollower) {
            this.mutualFollower = mutualFollower;
        }

        public static final class Builder {
            private String userFollowId;
            private boolean mutualFollower;

            private Builder() {
                userFollowId = null;
                mutualFollower = false;
            }

            public Builder userFollowId(String val) {
                userFollowId = val;
                return this;
            }

            public Builder mutualFollower(boolean val) {
                mutualFollower = val;
                return this;
            }

            public MineBackup build() {
                return new MineBackup(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.userFollowId);
            dest.writeByte(this.mutualFollower ? (byte) 1 : (byte) 0);
        }

        protected MineBackup(Parcel in) {
            this.userFollowId = in.readString();
            this.mutualFollower = in.readByte() != 0;
        }

        public static final Creator<MineBackup> CREATOR = new Creator<MineBackup>() {
            @Override
            public MineBackup createFromParcel(Parcel source) {
                return new MineBackup(source);
            }

            @Override
            public MineBackup[] newArray(int size) {
                return new MineBackup[size];
            }
        };
    }


    public void update(User user) {
        setRouter(user.getRouter() == null ? "" : user.getRouter());
        setAccount(user.getAccount() == null ? "" : user.getAccount());
        setAvatar(user.getAvatar() == null ? "" : user.getAvatar());
        setMiniAvatar(user.getMiniAvatar() == null ? "" : user.getMiniAvatar());
        setMobile(user.getMobile() == null ? "" : user.getMobile());
        setMobileVerified(user.getMobileVerified());
        setLevel(user.getLevel());
        setStatus(user.getStatus());
        setCreateTime(user.getCreateTime());
        setUpdateTime(user.getUpdateTime());
        setSlideBackup(user.getSlideBackup() == null ? new LinkedList<SlideImage>() : user.getSlideBackup());
        setMoreBackup(user.getMoreBackup() == null ? new MoreBackup() : user.getMoreBackup());
        setStatisticsBackup(user.getStatisticsBackup() == null ? new StatisticsBackup() : user.getStatisticsBackup());
        setMineBackup(user.getMineBackup() == null ? new MineBackup() : user.getMineBackup());
        setAvocation(user.getAvocation() == null ? new LinkedList<Tag>() : user.getAvocation());
        setColumnBackup(user.getColumnBackup() == null ? new LinkedList<Tag>() : user.getColumnBackup());
        setChannel(user.getChannel() == null ? Tag.newBuilder().groupType(SetupUtil.GROUP_TYPE_CHANNEL).build() : user.getChannel());
        setNewUser(user.newUser);
        setWalletPassword(user.walletPassword == null ? new WalletPassword() : user.getWalletPassword());
        setHasWalletPassword(user.isHasWalletPassword());
    }


    public static class TokenBackup implements Parcelable{
        public String access_token;
        public String token_type;
        public String refresh_token;
        public Long expires_in;
        public String scope;
        public String guestAccessTokenBackup;
        public String guestRefreshTokenBackup;

        public TokenBackup() {
            access_token = "";
            token_type = "";
            refresh_token = TOKEN_TYPE_GUEST;
            expires_in = 0L;
            scope = "";
            guestRefreshTokenBackup = "";
            guestAccessTokenBackup = "";
        }

        private TokenBackup(Builder builder) {
            setAccess_token(builder.access_token);
            setToken_type(builder.token_type);
            setRefresh_token(builder.refresh_token);
            setExpires_in(builder.expires_in);
            setScope(builder.scope);
            setGuestAccessTokenBackup(builder.guestAccessTokenBackup);
            setGuestRefreshTokenBackup(builder.guestRefreshTokenBackup);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public String getGuestAccessTokenBackup() {
            return guestAccessTokenBackup;
        }

        public void setGuestAccessTokenBackup(String guestAccessTokenBackup) {
            this.guestAccessTokenBackup = guestAccessTokenBackup;
        }

        public String getGuestRefreshTokenBackup() {
            return guestRefreshTokenBackup;
        }

        public void setGuestRefreshTokenBackup(String guestRefreshTokenBackup) {
            this.guestRefreshTokenBackup = guestRefreshTokenBackup;
        }

        public String getAccess_token() {
            return access_token;
        }

        public void setAccess_token(String access_token) {
            this.access_token = access_token;
        }

        public String getToken_type() {
            return token_type;
        }

        public void setToken_type(String token_type) {
            this.token_type = token_type;
        }

        public String getRefresh_token() {
            return refresh_token;
        }

        public void setRefresh_token(String refresh_token) {
            this.refresh_token = refresh_token;
        }

        public Long getExpires_in() {
            return expires_in;
        }

        public void setExpires_in(Long expires_in) {
            this.expires_in = expires_in;
        }

        public String getScope() {
            return scope;
        }

        public void setScope(String scope) {
            this.scope = scope;
        }

        public String getUrlEncodedAccessToken() {
            if (TextUtils.isEmpty(access_token)) return "";
            try {
                return URLEncoder.encode(access_token, "UTF-8");
            } catch (Exception e) {
                return access_token;
            }
        }

        public String getUrlEncodedRefreshToken() {
            if (TextUtils.isEmpty(refresh_token)) return "";
            try {
                return URLEncoder.encode(refresh_token, "UTF-8");
            } catch (Exception e) {
                return refresh_token;
            }
        }


        public static final class Builder {
            private String access_token;
            private String token_type;
            private String refresh_token;
            private Long expires_in;
            private String scope;
            private String guestAccessTokenBackup;
            private String guestRefreshTokenBackup;

            private Builder() {
                access_token = null;
                token_type = null;
                refresh_token = null;
                expires_in = null;
                scope = null;
                guestAccessTokenBackup = null;
                guestRefreshTokenBackup = null;
            }

            public Builder access_token(String val) {
                access_token = val;
                return this;
            }

            public Builder token_type(String val) {
                token_type = val;
                return this;
            }

            public Builder refresh_token(String val) {
                refresh_token = val;
                return this;
            }

            public Builder expires_in(Long val) {
                expires_in = val;
                return this;
            }

            public Builder scope(String val) {
                scope = val;
                return this;
            }

            public Builder guestAccessTokenBackup(String val) {
                guestAccessTokenBackup = val;
                return this;
            }

            public Builder guestRefreshTokenBackup(String val) {
                guestRefreshTokenBackup = val;
                return this;
            }

            public TokenBackup build() {
                return new TokenBackup(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.access_token);
            dest.writeString(this.token_type);
            dest.writeString(this.refresh_token);
            dest.writeValue(this.expires_in);
            dest.writeString(this.scope);
            dest.writeString(this.guestAccessTokenBackup);
            dest.writeString(this.guestRefreshTokenBackup);
        }

        protected TokenBackup(Parcel in) {
            this.access_token = in.readString();
            this.token_type = in.readString();
            this.refresh_token = in.readString();
            this.expires_in = (Long) in.readValue(Long.class.getClassLoader());
            this.scope = in.readString();
            this.guestAccessTokenBackup = in.readString();
            this.guestRefreshTokenBackup = in.readString();
        }

        public static final Creator<TokenBackup> CREATOR = new Creator<TokenBackup>() {
            @Override
            public TokenBackup createFromParcel(Parcel source) {
                return new TokenBackup(source);
            }

            @Override
            public TokenBackup[] newArray(int size) {
                return new TokenBackup[size];
            }
        };
    }

    public static final class Builder {
        private String router;
        private String id;
        private String account;
        private String password;
        private String salt;
        private String avatar;
        private String miniAvatar;
        private String mobile;
        private Integer mobileVerified;
        private Integer level;
        private Integer status;
        private Long createTime;
        private Long updateTime;
        private String token;
        private ThirdOauthBackup thirdOauthBackup;
        private List<SlideImage> slideBackup;
        private MoreBackup moreBackup;
        private StatisticsBackup statisticsBackup;
        private MineBackup mineBackup;
        private Long loginTimestamp;
        private TokenBackup accessToken;
        private List<Tag> columnBackup;
        private List<Tag> avocation;
        private Tag channel;
        private boolean newUser;
        private WalletPassword walletPassword;
        private boolean hasWalletPassword;
        private IMBackup userAccidPassword;

        private Builder() {
            router = null;
            id = null;
            account = null;
            password = null;
            salt = null;
            avatar = null;
            miniAvatar = null;
            mobile = null;
            mobileVerified = null;
            level = null;
            status = null;
            createTime = null;
            updateTime = null;
            token = null;
            thirdOauthBackup = null;
            slideBackup = null;
            moreBackup = null;
            statisticsBackup = null;
            mineBackup = null;
            accessToken = null;
            columnBackup = null;
            channel = null;
            avocation = null;
            newUser = false;
            walletPassword = null;
            hasWalletPassword = false;
            userAccidPassword = null;
        }

        public Builder router(String val) {
            router = val;
            return this;
        }

        public Builder id(String val) {
            id = val;
            return this;
        }

        public Builder newUser(boolean newUser) {
            this.newUser = newUser;
            return this;
        }

        public Builder password(String val) {
            password = val;
            return this;
        }

        public Builder columnBackup(List<Tag> columnBackup) {
            this.columnBackup = columnBackup;
            return this;
        }

        public Builder channel(Tag channel) {
            this.channel = channel;
            return this;
        }

        public Builder avocation(List<Tag> avocation) {
            this.avocation = avocation;
            return this;
        }

        public Builder account(String account) {
            this.account = account;
            return this;
        }

        public Builder salt(String salt) {
            this.salt = salt;
            return this;
        }

        public Builder avatar(String avatar) {
            this.avatar = avatar;
            return this;
        }

        public Builder miniAvatar(String miniAvatar) {
            this.miniAvatar = miniAvatar;
            return this;
        }

        public Builder mobile(String mobile) {
            this.mobile = mobile;
            return this;
        }

        public Builder mobileVerified(Integer mobileVerified) {
            this.mobileVerified = mobileVerified;
            return this;
        }

        public Builder level(Integer level) {
            this.level = level;
            return this;
        }

        public Builder status(Integer status) {
            this.status = status;
            return this;
        }

        public Builder createTime(Long createTime) {
            this.createTime = createTime;
            return this;
        }

        public Builder updateTime(Long updateTime) {
            this.updateTime = updateTime;
            return this;
        }

        public Builder token(String token) {
            this.token = token;
            return this;
        }

        public Builder thirdOauthBackup(ThirdOauthBackup thirdOauthBackup) {
            this.thirdOauthBackup = thirdOauthBackup;
            return this;
        }

        public Builder slideBackup(List<SlideImage> slideBackup) {
            this.slideBackup = slideBackup;
            return this;
        }

        public Builder moreBackup(MoreBackup moreBackup) {
            this.moreBackup = moreBackup;
            return this;
        }

        public Builder statisticsBackup(StatisticsBackup statisticsBackup) {
            this.statisticsBackup = statisticsBackup;
            return this;
        }

        public Builder mineBackup(MineBackup mineBackup) {
            this.mineBackup = mineBackup;
            return this;
        }

        public Builder loginTimestamp(Long val) {
            loginTimestamp = val;
            return this;
        }

        public Builder accessToken(TokenBackup val) {
            accessToken = val;
            return this;
        }

        public Builder walletPassword(WalletPassword val) {
            walletPassword = val;
            return this;
        }

        public Builder hasWalletPassword(boolean val) {
            hasWalletPassword = val;
            return this;
        }

        public Builder userAccidPassword(IMBackup val) {
            userAccidPassword = userAccidPassword;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }

    public static class IMBackup implements Parcelable{
        String accid;
        String token;

        public IMBackup() {
            accid = "";
            token = "";
        }

        private IMBackup(Builder builder) {
            setAccid(builder.accid);
            setToken(builder.token);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public String getAccid() {
            return accid == null ? "" : accid;
        }

        public void setAccid(String accid) {
            this.accid = accid == null ? "" : accid;
        }

        public String getToken() {
            return token == null ? "" : token;
        }

        public void setToken(String token) {
            this.token = token == null ? "" : token;
        }

        public static final class Builder {
            private String accid;
            private String token;

            private Builder() {
            }

            public Builder accid(String val) {
                accid = val;
                return this;
            }

            public Builder token(String val) {
                token = val;
                return this;
            }

            public IMBackup build() {
                return new IMBackup(this);
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.accid);
            dest.writeString(this.token);
        }

        protected IMBackup(Parcel in) {
            this.accid = in.readString();
            this.token = in.readString();
        }

        public static final Creator<IMBackup> CREATOR = new Creator<IMBackup>() {
            @Override
            public IMBackup createFromParcel(Parcel source) {
                return new IMBackup(source);
            }

            @Override
            public IMBackup[] newArray(int size) {
                return new IMBackup[size];
            }
        };
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.id);
        dest.writeString(this.account);
        dest.writeString(this.password);
        dest.writeString(this.salt);
        dest.writeString(this.avatar);
        dest.writeString(this.miniAvatar);
        dest.writeString(this.mobile);
        dest.writeString(this.router);
        dest.writeValue(this.mobileVerified);
        dest.writeValue(this.level);
        dest.writeValue(this.status);
        dest.writeValue(this.createTime);
        dest.writeValue(this.updateTime);
        dest.writeString(this.token);
        dest.writeParcelable(this.thirdOauthBackup, flags);
        dest.writeTypedList(this.slideBackup);
        dest.writeParcelable(this.moreBackup, flags);
        dest.writeParcelable(this.statisticsBackup, flags);
        dest.writeParcelable(this.mineBackup, flags);
        dest.writeValue(this.loginTimestamp);
        dest.writeParcelable(this.accessToken, flags);
        dest.writeTypedList(this.columnBackup);
        dest.writeParcelable(this.channel, flags);
        dest.writeTypedList(this.avocation);
        dest.writeByte(this.newUser ? (byte) 1 : (byte) 0);
        dest.writeParcelable(this.userAccidPassword, flags);
        dest.writeSerializable(this.walletPassword);
        dest.writeByte(this.hasWalletPassword ? (byte) 1 : (byte) 0);
    }

    protected User(Parcel in) {
        this.id = in.readString();
        this.account = in.readString();
        this.password = in.readString();
        this.salt = in.readString();
        this.avatar = in.readString();
        this.miniAvatar = in.readString();
        this.mobile = in.readString();
        this.router = in.readString();
        this.mobileVerified = (Integer) in.readValue(Integer.class.getClassLoader());
        this.level = (Integer) in.readValue(Integer.class.getClassLoader());
        this.status = (Integer) in.readValue(Integer.class.getClassLoader());
        this.createTime = (Long) in.readValue(Long.class.getClassLoader());
        this.updateTime = (Long) in.readValue(Long.class.getClassLoader());
        this.token = in.readString();
        this.thirdOauthBackup = in.readParcelable(ThirdOauthBackup.class.getClassLoader());
        this.slideBackup = in.createTypedArrayList(SlideImage.CREATOR);
        this.moreBackup = in.readParcelable(MoreBackup.class.getClassLoader());
        this.statisticsBackup = in.readParcelable(StatisticsBackup.class.getClassLoader());
        this.mineBackup = in.readParcelable(MineBackup.class.getClassLoader());
        this.loginTimestamp = (Long) in.readValue(Long.class.getClassLoader());
        this.accessToken = in.readParcelable(TokenBackup.class.getClassLoader());
        this.columnBackup = in.createTypedArrayList(Tag.CREATOR);
        this.channel = in.readParcelable(Tag.class.getClassLoader());
        this.avocation = in.createTypedArrayList(Tag.CREATOR);
        this.newUser = in.readByte() != 0;
        this.userAccidPassword = in.readParcelable(IMBackup.class.getClassLoader());
        this.walletPassword = (WalletPassword) in.readSerializable();
        this.hasWalletPassword = in.readByte() != 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
}
